home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / +system+ / tools / gui / bgui.lha / bgui / Examples / Source / MultiColumn.c < prev    next >
C/C++ Source or Header  |  2000-02-27  |  36KB  |  814 lines

  1. /*
  2.  * @(#) $Header: /cvsroot/bgui/examples/Attic/MultiColumn.c,v 1.1.2.3 1999/02/19 05:03:56 mlemos Exp $
  3.  *
  4.  * MultiColumn.c
  5.  *
  6.  * (C) Copyright 1998 Manuel Lemos.
  7.  * (C) Copyright 1995 Jaba Development.
  8.  * (C) Copyright 1995 Jan van den Baard.
  9.  * All Rights Reserved.
  10.  *
  11.  * $Log: MultiColumn.c,v $
  12.  * Revision 1.1.2.3  1999/02/19 05:03:56  mlemos
  13.  * Added support to build with Storm C.
  14.  *
  15.  * Revision 1.1.2.2  1998/04/27 00:13:01  mlemos
  16.  * Ensured that the stack is never less than 8000 bytes.
  17.  *
  18.  * Revision 1.1.2.1  1998/02/28 17:45:30  mlemos
  19.  * Ian sources
  20.  *
  21.  *
  22.  */
  23.  
  24. /*
  25. dcc MultiColumn.c -proto -mi -ms -mRR -lbgui
  26. quit
  27. */
  28.  
  29. long __stack=8000;
  30.  
  31. #include "DemoCode.h"
  32.  
  33. #include <dos/exall.h>
  34. #include <utility/hooks.h>
  35.  
  36. #include <clib/macros.h>
  37.  
  38. #include <string.h>
  39. #include <stdio.h>
  40.  
  41. /*
  42. **      This is the data were going to add
  43. **      to the listview object. It is a simple
  44. **      structure in which the file-information
  45. **      is stored. This data is created in the
  46. **      LISTV_Resource hook from a pointer
  47. **      to a ExAllData structure.
  48. **/
  49. typedef struct {
  50.         UBYTE                   fi_FileName[ 108 ];
  51.         UBYTE                   fi_Size[ 11 ];
  52.         UBYTE                   fi_Date[ 32 ];
  53.         BOOL                    fi_IsDir;
  54. } FILEINFO;
  55.  
  56. /*
  57. **      The LISTV_Resource hook is used to create
  58. **      the FILEINFO structures from a struct ExAllData
  59. **      at create time. At delete time the FILEINFO
  60. **      structure is simply deallocated.
  61. **/
  62. SAVEDS ASM APTR ResourceHookFunc( REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct lvResource *lvr )
  63. {
  64.         struct ExAllData        *ead;
  65.         FILEINFO                *fi;
  66.         struct DateTime          dt;
  67.         APTR                     return_code = NULL;
  68.  
  69.         /*
  70.         **      What must we do?
  71.         **/
  72.         switch ( lvr->lvr_Command ) {
  73.  
  74.                 case    LVRC_MAKE:
  75.                         /*
  76.                         **      Create a FILEINFO structure.
  77.                         **      BGUI has passed us a pointer to a
  78.                         **      ExAllData structure. Here we
  79.                         **      convert it to a FILEINFO structure
  80.                         **      which, eventually, get's added to
  81.                         **      the listview.
  82.                         **/
  83.                         if ( fi = ( FILEINFO * )AllocVec( sizeof( FILEINFO ), MEMF_PUBLIC )) {
  84.                                 /*
  85.                                 **      Pick up the ExAllData.
  86.                                 **/
  87.                                 ead = ( struct ExAllData * )lvr->lvr_Entry;
  88.                                 /*
  89.                                 **      Copy the name.
  90.                                 **/
  91.                                 strcpy( &fi->fi_FileName[ 0 ], ead->ed_Name );
  92.                                 /*
  93.                                 **      Format the size text. We can do all sorts of
  94.                                 **      fancy stuff here like using the locale.library
  95.                                 **      formatting stuff but hey, it's just a demo ;)
  96.                                 **/
  97.                                 if ( ead->ed_Type < 0 ) {
  98.                                         fi->fi_IsDir = FALSE;
  99.                                         sprintf( &fi->fi_Size[ 0 ], "%ld", ead->ed_Size );
  100.                                 } else {
  101.                                         fi->fi_IsDir = TRUE;
  102.                                         strcpy( &fi->fi_Size[ 0 ], "(dir)" );
  103.                                 }
  104.                                 /*
  105.                                 **      Convert the date to a string.
  106.                                 **/
  107.                                 dt.dat_Stamp    = *(( struct DateStamp * )&ead->ed_Days );
  108.                                 dt.dat_Format   = FORMAT_CDN;
  109.                                 dt.dat_Flags    = DTF_SUBST | DTF_FUTURE;
  110.                                 dt.dat_StrDay   = NULL;
  111.                                 dt.dat_StrDate  = &fi->fi_Date[ 0 ];
  112.                                 dt.dat_StrTime  = NULL;
  113.                                 /*
  114.                                 **      Format date.
  115.                                 **/
  116.                                 DateToStr( &dt );
  117.                                 /*
  118.                                 **      Return a pointer to the created
  119.                                 **      FILEINFO structure.
  120.                                 **/
  121.                                 return_code = ( APTR )fi;
  122.                         }
  123.                         break;
  124.  
  125.                 case    LVRC_KILL:
  126.                         /*
  127.                         **      Simply deallocate the FILEINFO
  128.                         **      structure which has been created with
  129.                         **      LVRC_MAKE above.
  130.                         **/
  131.                         FreeVec( lvr->lvr_Entry );
  132.                         break;
  133.         }
  134.         /*
  135.         **      Pointer to FILEINFO or NULL.
  136.         **/
  137.         return( return_code );
  138. }
  139.  
  140. /*
  141. **      The listview will have three columns.
  142. **
  143. **      Name            Size            Date
  144. **
  145. **      The following globals will contain the maximum
  146. **      width of each of these columns.
  147. **/
  148. UWORD   MaxName, MaxSize, MaxDate;
  149.  
  150. /*
  151. **      This global stores the total width of the
  152. **      listview drawing area.
  153. **/
  154. UWORD   TotalWidth = 0;
  155.  
  156. /*
  157. **      This boolean determines wether the hook must
  158. **      re-compute the column sizes.
  159. **/
  160. BOOL    ReCompCols = TRUE;
  161.  
  162. /*
  163. **      We use 16 pixels as a minimum inner-column spacing.
  164. **/
  165. #define INNER_SPACE                     16
  166.  
  167. /*
  168. **      This routine re-computes the minimum column
  169. **      sizes when necessary.
  170. **/
  171. VOID ReComputeColumns( struct RastPort *rp, Object *obj, UWORD list_width )
  172. {
  173.         FILEINFO                        *fi;
  174.         UWORD                            tmp, total;
  175.  
  176.         /*
  177.         **      A re-computation is necessary when:
  178.         **
  179.         **      1) The ReCompCols flag is TRUE.
  180.         **      2) The with of the listview has changed.
  181.         **/
  182.         if ( ReCompCols || ( TotalWidth != list_width )) {
  183.                 /*
  184.                 **      Our listview also has a title entry.
  185.                 **      Here we compute the default column
  186.                 **      sizes accoording to this title.
  187.                 **/
  188.                 MaxName = TextLength( rp, "Name:", 6 ) + INNER_SPACE;
  189.                 MaxSize = TextLength( rp, "Size:", 6 ) + INNER_SPACE;
  190.                 MaxDate = TextLength( rp, "Date:", 6 );
  191.                 /*
  192.                 **      Now we loop through the entries to find
  193.                 **      out the largest width of the three columns.
  194.                 **/
  195.                 if ( fi = ( FILEINFO * )FirstEntry( obj )) {
  196.                         /*
  197.                         **      Loop until all are done.
  198.                         **/
  199.                         while ( fi ) {
  200.                                 /*
  201.                                 **      Compute width of the Name: column
  202.                                 **      for this entry.
  203.                                 **/
  204.                                 tmp = TextLength( rp, &fi->fi_FileName[ 0 ], strlen( &fi->fi_FileName[ 0 ] )) + INNER_SPACE;
  205.                                 /*
  206.                                 **      Is it bigger than the last one?
  207.                                 **      If so store it.
  208.                                 **/
  209.                                 if ( tmp > MaxName ) MaxName = tmp;
  210.                                 /*
  211.                                 **      Compute width of the Size: column
  212.                                 **      for this entry.
  213.                                 **/
  214.                                 tmp = TextLength( rp, &fi->fi_Size[ 0 ], strlen( &fi->fi_Size[ 0 ] )) + INNER_SPACE;
  215.                                 /*
  216.                                 **      Is it bigger than the last one?
  217.                                 **      If so store it.
  218.                                 **/
  219.                                 if ( tmp > MaxSize ) MaxSize = tmp;
  220.                                 /*
  221.                                 **      Compute width of the Date: column
  222.                                 **      for this entry.
  223.                                 **/
  224.                                 tmp = TextLength( rp, &fi->fi_Date[ 0 ], strlen( &fi->fi_Date[ 0 ] ));
  225.                                 /*
  226.                                 **      Is it bigger than the last one?
  227.                                 **      If so store it.
  228.                                 **/
  229.                                 if ( tmp > MaxDate ) MaxDate = tmp;
  230.                                 /*
  231.                                 **      Pick up the next entry.
  232.                                 **/
  233.                                 fi = ( FILEINFO * )NextEntry( obj, fi );
  234.                         }
  235.                 }
  236.                 /*
  237.                 **      Compute the total columns width.
  238.                 **/
  239.                 total = MaxName + MaxSize + MaxDate;
  240.                 /*
  241.                 **      If there's room left over we
  242.                 **      distribute it between the columns so
  243.                 **      we get a nice even spacing between
  244.                 **      them.
  245.                 **/
  246.                 if ( list_width > total ) {
  247.                         MaxName += ( list_width - total ) >> 1;
  248.                         MaxSize += ( list_width - total ) >> 1;
  249.                 }
  250.                 /*
  251.                 **      All done. Set the re-compute flag to
  252.                 **      FALSE and store the list width.
  253.                 **/
  254.                 ReCompCols = FALSE;
  255.                 TotalWidth = list_width;
  256.         }
  257. }
  258.  
  259. /*
  260. **      The default DrawInfo pens. Just in case we don't
  261. **      get them from the system.
  262. **/
  263. UWORD   DefDriPens[] = {
  264.         0, 1, 1, 2, 1, 3, 1, 0, 2, 1, 2, 1 };
  265.  
  266. /*
  267. **      Listview rendering hook. Here's where the magic starts ;)
  268. **/
  269. SAVEDS ASM UBYTE *DisplayHookFunc( REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct lvRender *lvr )
  270. {
  271.         struct TextExtent               te;
  272.         UBYTE                          *str;
  273.         FILEINFO                       *fi = ( FILEINFO * )lvr->lvr_Entry;
  274.         UWORD                          *pens, numc, w, l, cw, h;
  275.  
  276.         /*
  277.         **      Pick up the DrawInfo pen array.
  278.         **/
  279.         pens = lvr->lvr_DrawInfo ? lvr->lvr_DrawInfo->dri_Pens : DefDriPens;
  280.         /*
  281.         **      Pick up the width of the list.
  282.         **/
  283.         w = lvr->lvr_Bounds.MaxX - lvr->lvr_Bounds.MinX + 1;
  284.         /*
  285.         **      Pick up the list left-edge;
  286.         **/
  287.         l = lvr->lvr_Bounds.MinX;
  288.         /*
  289.         **      Pick up the height of the entry.
  290.         **/
  291.         h = lvr->lvr_Bounds.MaxY - lvr->lvr_Bounds.MinY + 1;
  292.  
  293.         /*
  294.         **      First we render the background.
  295.         **/
  296.         SetAPen( lvr->lvr_RPort, lvr->lvr_State == LVRS_SELECTED ? pens[ FILLPEN ] : pens[ BACKGROUNDPEN ] );
  297.         SetDrMd( lvr->lvr_RPort, JAM1 );
  298.  
  299.         RectFill( lvr->lvr_RPort, lvr->lvr_Bounds.MinX,
  300.                                   lvr->lvr_Bounds.MinY,
  301.                                   lvr->lvr_Bounds.MaxX,
  302.                                   lvr->lvr_Bounds.MaxY );
  303.  
  304.         /*
  305.         **      When we are passed a NULL entry pointer
  306.         **      we are presumed to render the title. If your
  307.         **      listview does not have a title simply
  308.         **      recompute the columns and return NULL.
  309.         **      We have a title so here we go.
  310.         **/
  311.         if ( ! fi ) {
  312.                 /*
  313.                 **      Recompute the column sizes. The routine
  314.                 **      itself will decide if it's necessary.
  315.                 **/
  316.                 ReComputeColumns( lvr->lvr_RPort, obj, w );
  317.                 /*
  318.                 **      Set the pen for the title-entry.
  319.                 **/
  320.                 SetAPen( lvr->lvr_RPort, pens[ FILLPEN ] );
  321.         } else {
  322.                 /*
  323.                 **      Set the pen for a non-title entry. Ofcourse
  324.                 **      we can (should?) differenciate between normal and
  325.                 **      selected here but I wont ;)
  326.                 **/
  327.                 if ( fi->fi_IsDir ) SetAPen( lvr->lvr_RPort, pens[ HIGHLIGHTTEXTPEN ] );
  328.                 else                SetAPen( lvr->lvr_RPort, pens[ TEXTPEN ] );
  329.         }
  330.         /*
  331.         **      Obtain Name: column width. We check it against the
  332.         **      total list width so we do not go outside the
  333.         **      given area.
  334.         **/
  335.         cw = MIN( MaxName, w );
  336.  
  337.         /*
  338.         **      Pick up the name string or, when this
  339.         **      is a title call, the string "Name:".
  340.         **/
  341.         str = fi ? &fi->fi_FileName[ 0 ] : ( UBYTE * )"Name:";
  342.  
  343.         /*
  344.         **      Compute the number of character we
  345.         **      can render.
  346.         **/
  347.         numc = TextFit( lvr->lvr_RPort, str, strlen( str ), &te, NULL, 0, cw, h );
  348.  
  349.         /*
  350.         **      If the number of characters is
  351.         **      0 we can stop right here and now.
  352.         **/
  353.         if ( ! numc ) return( NULL );
  354.  
  355.         /*
  356.         **      Move to the correct position
  357.         **      and render the text.
  358.         **/
  359.         Move( lvr->lvr_RPort, l, lvr->lvr_Bounds.MinY + lvr->lvr_RPort->TxBaseline );
  360.         Text( lvr->lvr_RPort, str, numc );
  361.  
  362.         /*
  363.         **      Adjust the left-edge and width to
  364.         **      get past the Name: column.
  365.         **/
  366.         l += cw;
  367.         w  = MAX(( WORD )( w - cw ), 0 );
  368.  
  369.         /*
  370.         **      Obtain Size: column width. We check it against the
  371.         **      total list width so we do not go outside the
  372.         **      given area.
  373.         **/
  374.         cw = MIN( MaxSize, w );
  375.  
  376.         /*
  377.         **      Pick up the size string or, when this
  378.         **      is a title call, the string "Size:".
  379.         **/
  380.         str = fi ? &fi->fi_Size[ 0 ] : ( UBYTE * )"Size:";
  381.  
  382.         /*
  383.         **      Compute the number of character we
  384.         **      can render.
  385.         **/
  386.         numc = TextFit( lvr->lvr_RPort, str, strlen( str ), &te, NULL, 0, cw, h );
  387.  
  388.         /*
  389.         **      If the number of characters is
  390.         **      0 we can stop right here and now.
  391.         **/
  392.         if ( ! numc ) return( NULL );
  393.  
  394.         /*
  395.         **      Move to the correct position
  396.         **      and render the text.
  397.         **/
  398.         Move( lvr->lvr_RPort, l, lvr->lvr_Bounds.MinY + lvr->lvr_RPort->TxBaseline );
  399.         Text( lvr->lvr_RPort, str, numc );
  400.  
  401.         /*
  402.         **      Adjust the left-edge and width to
  403.         **      get past the Size: column.
  404.         **/
  405.         l += cw;
  406.         w  = MAX(( WORD )( w - cw ), 0 );
  407.  
  408.         /*
  409.         **      Obtain Date column width. We check it against the
  410.         **      total list width so we do not go outside the
  411.         **      given area.
  412.         **/
  413.         cw = MIN( MaxDate, w );
  414.  
  415.         /*
  416.         **      Pick up the date string or, when this
  417.         **      is a title call, the string "Date:".
  418.         **/
  419.         str = fi ? &fi->fi_Date[ 0 ] : ( UBYTE * )"Date:";
  420.  
  421.         /*
  422.         **      Compute the number of character we
  423.         **      can render.
  424.         **/
  425.         numc = TextFit( lvr->lvr_RPort, str, strlen( str ), &te, NULL, 0, cw, h );
  426.  
  427.         /*
  428.         **      If the number of characters is
  429.         **      0 we can stop right here and now.
  430.         **/
  431.         if ( ! numc ) return( NULL );
  432.  
  433.         /*
  434.         **      Move to the correct position
  435.         **      and render the text.
  436.         **/
  437.         Move( lvr->lvr_RPort, l, lvr->lvr_Bounds.MinY + lvr->lvr_RPort->TxBaseline );
  438.         Text( lvr->lvr_RPort, str, numc );
  439.  
  440.         /*
  441.         **      Return NULL. This is important. If we return a non-NULL
  442.         **      value the listview class will think it is a pointer to
  443.         **      the text to render and try to render it.
  444.         **/
  445.         return( NULL );
  446. }
  447.  
  448. /*
  449. **      The comparrison hook. We do a simple name, dir/file
  450. **      comparrison here.
  451. **/
  452. SAVEDS ASM LONG CompareHookFunc( REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct lvCompare *lvc )
  453. {
  454.         FILEINFO                *a = ( FILEINFO * )lvc->lvc_EntryA;
  455.         FILEINFO                *b = ( FILEINFO * )lvc->lvc_EntryB;
  456.  
  457.         /*
  458.         **      First we do a type comparrison to get the
  459.         **      directories at the top of the list.
  460.         **/
  461.         if ( a->fi_IsDir && ! b->fi_IsDir      ) return( -1L );
  462.         else if ( ! a->fi_IsDir && b->fi_IsDir ) return( 1L );
  463.  
  464.         /*
  465.         **      Otherwise we do a simple, case insensitive,
  466.         **      name string comparrison.
  467.         **/
  468.         return( stricmp( &a->fi_FileName[ 0 ], &b->fi_FileName[ 0 ] ));
  469. }
  470.  
  471. /*
  472. **      A IDCMP hook for the window which allows us
  473. **      to control the listview from the keyboard.
  474. **/
  475. SAVEDS ASM VOID ScrollHookFunc( REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct IntuiMessage *msg )
  476. {
  477.         struct Window                   *window;
  478.         Object                          *lv_obj = ( Object * )hook->h_Data;
  479.  
  480.         /*
  481.         **      Obtain window pointer.
  482.         **/
  483.         GetAttr( WINDOW_Window,        obj,    ( ULONG * )&window );
  484.  
  485.         /*
  486.         **      What key is pressed?
  487.         **/
  488.         switch ( msg->Code ) {
  489.  
  490.                 case    0x4C:
  491.                         /*
  492.                         **      UP              - Move entry up.
  493.                         **      SHIFT + UP      - Move page up.
  494.                         **      CTRL + UP       - Move to the top.
  495.                         **/
  496.                         if ( msg->Qualifier & ( IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT ))
  497.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Page_Up, TAG_END );
  498.                         else if ( msg->Qualifier & IEQUALIFIER_CONTROL )
  499.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_First, TAG_END );
  500.                         else
  501.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Previous, TAG_END );
  502.                         break;
  503.  
  504.                 case    0x4D:
  505.                         /*
  506.                         **      DOWN            - Move entry down.
  507.                         **      SHIFT + DOWN    - Move page down.
  508.                         **      CTRL + DOWN     - Move to the end.
  509.                         **/
  510.                         if ( msg->Qualifier & ( IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT ))
  511.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Page_Down, TAG_END );
  512.                         else if ( msg->Qualifier & IEQUALIFIER_CONTROL )
  513.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Last, TAG_END );
  514.                         else
  515.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Next, TAG_END );
  516.  
  517.                         break;
  518.  
  519.                 case    0x43:
  520.                 case    0x44:
  521.                         /*
  522.                         **      RETURN or ENTER - Report the listview ID to the event handler.
  523.                         **/
  524.                         DoMethod( obj, WM_REPORT_ID, (( struct Gadget * )lv_obj )->GadgetID, 0L );
  525.                         break;
  526.         }
  527. }
  528.  
  529. /*
  530. **      The hook structures as added to the
  531. **      listview object and window object.
  532. **
  533. **      If your compiler complaints about the
  534. **      HOOKFUNC typedef uncomment the below line.
  535. **/
  536.  
  537. /* typedef ULONG (*HOOKFUNC)(); */
  538.  
  539. struct Hook ResourceHook = { NULL, NULL, (HOOKFUNC)ResourceHookFunc, NULL, NULL };
  540. struct Hook DisplayHook  = { NULL, NULL, (HOOKFUNC)DisplayHookFunc,  NULL, NULL };
  541. struct Hook CompareHook  = { NULL, NULL, (HOOKFUNC)CompareHookFunc,  NULL, NULL };
  542. struct Hook ScrollHook   = { NULL, NULL, (HOOKFUNC)ScrollHookFunc,   NULL, NULL };
  543.  
  544. /*
  545. **      Scan the directory "name".
  546. **/
  547. VOID ScanDirectory( UBYTE *name, Object *obj )
  548. {
  549.         struct ExAllControl             *eac;
  550.         struct ExAllData                *ead, *tmp;
  551.         struct FileInfoBlock            *fib;
  552.         BPTR                             lock;
  553.         BOOL                             ismore;
  554.  
  555.         /*
  556.         **      We need to recompute the columns.
  557.         **/
  558.         ReCompCols = TRUE;
  559.  
  560.         /*
  561.         **      Get a lock to the directory.
  562.         **/
  563.         if ( lock = Lock( name, ACCESS_READ )) {
  564.                 /*
  565.                 **      Allocate a FileInfoBlock structure.
  566.                 **/
  567.                 if ( fib = ( struct FileInfoBlock * )AllocDosObject( DOS_FIB, NULL )) {
  568.                         /*
  569.                         **      Examine the lock.
  570.                         **/
  571.                         if ( Examine( lock, fib )) {
  572.                                 /*
  573.                                 **      Is this a directory?
  574.                                 **/
  575.                                 if ( fib->fib_DirEntryType > 0 ) {
  576.                                         /*
  577.                                         **      Allocate ExAll() control structure.
  578.                                         **/
  579.                                         if ( eac = ( struct ExAllControl * )AllocDosObject( DOS_EXALLCONTROL, NULL )) {
  580.                                                 /*
  581.                                                 **      Set key to NULL.
  582.                                                 **/
  583.                                                 eac->eac_LastKey = NULL;
  584.                                                 /*
  585.                                                 **      Allocate ExAll() buffer.
  586.                                                 **/
  587.                                                 if ( ead = ( struct ExAllData * )AllocVec( 10 * sizeof( struct ExAllData ), MEMF_PUBLIC )) {
  588.                                                         /*
  589.                                                         **      Read directory.
  590.                                                         **/
  591.                                                         do {
  592.                                                                 /*
  593.                                                                 **      Fill buffer.
  594.                                                                 **/
  595.                                                                 ismore = ExAll( lock, ead, 10 * sizeof( struct ExAllData ), ED_DATE, eac );
  596.  
  597.                                                                 /*
  598.                                                                 **      Errors? Done?
  599.                                                                 **/
  600.                                                                 if (( ! ismore ) && ( IoErr() != ERROR_NO_MORE_ENTRIES ))
  601.                                                                         break;
  602.  
  603.                                                                 /*
  604.                                                                 **      Entries read?
  605.                                                                 **/
  606.                                                                 if ( ! eac->eac_Entries )
  607.                                                                         continue;
  608.  
  609.                                                                 /*
  610.                                                                 **      Pick up data pointer.
  611.                                                                 **/
  612.                                                                 tmp = ead;
  613.  
  614.                                                                 /*
  615.                                                                 **      Add the entries.
  616.                                                                 **/
  617.                                                                 do {
  618.                                                                         AddEntry( NULL, obj, tmp, LVAP_SORTED );
  619.                                                                         /*
  620.                                                                         **      Next...
  621.                                                                         **/
  622.                                                                         tmp = tmp->ed_Next;
  623.                                                                 } while ( tmp );
  624.                                                         } while ( ismore );
  625.                                                         /*
  626.                                                         **      Deallocate ExAll() buffer.
  627.                                                         **/
  628.                                                         FreeVec( ead );
  629.                                                 }
  630.                                                 /*
  631.                                                 **      Deallocate ExAll() control structure.
  632.                                                 **/
  633.                                                 FreeDosObject( DOS_EXALLCONTROL, eac );
  634.                                         }
  635.                                 }
  636.                         }
  637.                         /*
  638.                         **      Deallocate FileInfoBlock structure.
  639.                         **/
  640.                         FreeDosObject( DOS_FIB, fib );
  641.                 }
  642.                 /*
  643.                 **      Release lock.
  644.                 **/
  645.                 UnLock( lock );
  646.         }
  647. }
  648.  
  649. /*
  650. **      And were off...
  651. **/
  652. #define ID_QUIT                 1
  653. #define ID_LIST                 2
  654. #define ID_NEWDIR               3
  655.  
  656. VOID StartDemo( void )
  657. {
  658.         struct RDArgs                   *ra;
  659.         struct Window                   *win;
  660.         Object                          *WO_DirWin, *GO_DirList, *GO_Quit, *GO_NewDir;
  661.         FILEINFO                        *fi;
  662.         LONG                             dname = 0L;
  663.         ULONG                            signal, rc;
  664.         UBYTE                            name[ 512 ], *ptr;
  665.         BOOL                             running = TRUE;
  666.  
  667.         /*
  668.         **      Parse command line?
  669.         **/
  670.         if ( ra = ReadArgs( "NAME", &dname, NULL )) {
  671.                 /*
  672.                 **      Copy the name into the buffer.
  673.                 **/
  674.                 if ( dname ) strcpy( name, ( UBYTE * )dname );
  675.                 else         name[ 0 ] = 0;
  676.                 /*
  677.                 **      Create the listview object.
  678.                 **/
  679.                 GO_DirList = ListviewObject,
  680.                         LISTV_ResourceHook,             &ResourceHook,
  681.                         LISTV_DisplayHook,              &DisplayHook,
  682.                         LISTV_TitleHook,                &DisplayHook,
  683.                         LISTV_CompareHook,              &CompareHook,
  684.                         GA_ID,                          ID_LIST,
  685.                 EndObject;
  686.                 /*
  687.                 **      Put it in the IDCMP hook.
  688.                 **/
  689.                 ScrollHook.h_Data = ( APTR )GO_DirList;
  690.                 /*
  691.                 **      Create the window.
  692.                 **/
  693.                 WO_DirWin = WindowObject,
  694.                         WINDOW_Title,           "MultiCol",
  695.                         WINDOW_RMBTrap,         TRUE,
  696.                         WINDOW_ScaleWidth,      50,
  697.                         WINDOW_ScaleHeight,     30,
  698.                         WINDOW_AutoAspect,      TRUE,
  699.                         WINDOW_SmartRefresh,    TRUE,
  700.                         WINDOW_IDCMPHookBits,   IDCMP_RAWKEY,
  701.                         WINDOW_IDCMPHook,       &ScrollHook,
  702.                         WINDOW_MasterGroup,
  703.                                 VGroupObject, HOffset( 4 ), VOffset( 4 ), Spacing( 4 ), GROUP_BackFill, SHINE_RASTER,
  704.                                         StartMember,
  705.                                                 VGroupObject,
  706.                                                         StartMember, GO_DirList, EndMember,
  707.                                                         StartMember,
  708.                                                                 GO_NewDir = KeyString( NULL, name, 512, ID_NEWDIR ), FixMinHeight,
  709.                                                         EndMember,
  710.                                                 EndObject,
  711.                                         EndMember,
  712.                                         StartMember,
  713.                                                 HGroupObject,
  714.                                                         VarSpace( DEFAULT_WEIGHT ),
  715.                                                         StartMember, GO_Quit = KeyButton( "_Quit", ID_QUIT ), EndMember,
  716.                                                         VarSpace( DEFAULT_WEIGHT ),
  717.                                                 EndObject, FixMinHeight,
  718.                                         EndMember,
  719.                                 EndObject,
  720.                 EndObject;
  721.  
  722.                 /*
  723.                 **      Window created OK?
  724.                 **/
  725.                 if ( WO_DirWin ) {
  726.                         /*
  727.                         **      Add gadget key.
  728.                         **/
  729.                         if ( GadgetKey( WO_DirWin, GO_Quit, "q" )) {
  730.                                 /*
  731.                                 **      Open the window.
  732.                                 **/
  733.                                 if ( win = WindowOpen( WO_DirWin )) {
  734.                                         /*
  735.                                         **      Obtain signal mask.
  736.                                         **/
  737.                                         GetAttr( WINDOW_SigMask, WO_DirWin, &signal );
  738.                                         /*
  739.                                         **      Read in the directory.
  740.                                         **/
  741.                                         WindowBusy( WO_DirWin );
  742.                                         ScanDirectory( name, GO_DirList );
  743.                                         WindowReady( WO_DirWin );
  744.                                         /*
  745.                                         **      Refresh the list.
  746.                                         **/
  747.                                         RefreshList( win, GO_DirList );
  748.                                         /*
  749.                                         **      Poll messages...
  750.                                         **/
  751.                                         do {
  752.                                                 Wait( signal );
  753.                                                 while (( rc = HandleEvent( WO_DirWin )) != WMHI_NOMORE ) {
  754.                                                         switch ( rc ) {
  755.  
  756.                                                                 case    ID_QUIT:
  757.                                                                 case    WMHI_CLOSEWINDOW:
  758.                                                                         running = FALSE;
  759.                                                                         break;
  760.  
  761.                                                                 case    ID_LIST:
  762.                                                                         /*
  763.                                                                         **      Get selected entry.
  764.                                                                         **/
  765.                                                                         if ( fi = ( FILEINFO * )FirstSelected( GO_DirList )) {
  766.                                                                                 /*
  767.                                                                                 **      Is the entry a directory?
  768.                                                                                 **/
  769.                                                                                 if ( fi->fi_IsDir ) {
  770.                                                                                         /*
  771.                                                                                         **      AddPart() the name to the buffer.
  772.                                                                                         **/
  773.                                                                                         AddPart( name, &fi->fi_FileName[ 0 ], 512 );
  774.                                                                                         /*
  775.                                                                                         **      Refresh the string gadget.
  776.                                                                                         **/
  777.                                                                                         SetGadgetAttrs(( struct Gadget * )GO_NewDir, win, NULL, STRINGA_TextVal, name, TAG_END );
  778.                                                                                         /*
  779.                                                                                         **      Re-read the list.
  780.                                                                                         **/
  781.                                                                                         refreshDir:
  782.                                                                                         WindowBusy( WO_DirWin );
  783.                                                                                         ClearList( win, GO_DirList );
  784.                                                                                         ScanDirectory( name, GO_DirList );
  785.                                                                                         RefreshList( win, GO_DirList );
  786.                                                                                         WindowReady( WO_DirWin );
  787.                                                                                 }
  788.                                                                         }
  789.                                                                         break;
  790.  
  791.                                                                 case    ID_NEWDIR:
  792.                                                                         /*
  793.                                                                         **      Copy the new name to the buffer.
  794.                                                                         **/
  795.                                                                         GetAttr( STRINGA_TextVal, GO_NewDir, ( ULONG * )&ptr );
  796.                                                                         strcpy( name, ptr );
  797.                                                                         goto refreshDir;
  798.                                                         }
  799.                                                 }
  800.                                         } while ( running );
  801.                                 }
  802.                         }
  803.                         /*
  804.                         **      Kill the object.
  805.                         **/
  806.                         DisposeObject( WO_DirWin );
  807.                 }
  808.                 /*
  809.                 **      Delete the ReadArgs structure.
  810.                 **/
  811.                 FreeArgs( ra );
  812.         }
  813. }
  814.